/*
 * Ethan Levine
 * 
 * The contents of this file are subject to the GNU General Public
 * License (GPL) v2.  The full contents of this license can be
 * found at Mathma's website, http://www.codeplex.com/mathma/license
 */

package mathma.core.real.form;

import java.util.List;
import java.util.ArrayList;

import mathma.core.form.MultiExpression;
import mathma.core.form.UnknownSuspensionException;

import mathma.core.expr.Variable;
import mathma.core.expr.Expression;
import mathma.core.real.FiniteReal;
import mathma.core.real.Real;

/**
 * @since 0.1.5
 * @author Ethan Levine
 */
public class MultiplicationExpression extends MultiExpression<Real, Real> {
    
    public MultiplicationExpression(Expression<Real>... operands) {
        super(Real.Type, operands);
    }
    
    public MultiplicationExpression(List<Expression<Real>> operands) {
        super(Real.Type, operands);
    }
    
    @Override
    public Real evaluate() {
        Real total = Real.ONE;
        for (Expression<Real> operand : getOperands()) {
            total.multiply(operand.evaluate());
        }
        return total;
    }
    
    @Override
    public Expression<Real> differentiate(Variable<Real> var)
            throws UnknownSuspensionException {
        /* METHOD:
         * (f * g * h * j * k)' = f'ghjk + fg'hjk + fgh'jk + fghj'k + fghjk'
         */
        List<Expression<Real>> addOperands = new ArrayList<Expression<Real>>();
        for (int i = 0; i < getOperands().size(); i++) {
            List<Expression<Real>> multOperands = new ArrayList<Expression<Real>>();
            for (int j = 0; j < getOperands().size(); j++) {
                if (j == i) {
                    multOperands.add(getOperands().get(j).differentiate(var));
                } else {
                    multOperands.add(getOperands().get(j));
                }
            }
            addOperands.add(new MultiplicationExpression(multOperands));
        }
        return new AdditionExpression(addOperands);
    }
    
    @Override
    public MultiplicationExpression newInstance(List<Expression<Real>> operands) {
        return new MultiplicationExpression(operands);
    }
}
